package demo.security;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
public class ClientDetailConfiguration {
	
	@Autowired	
	private PasswordEncoder passwordEncoder;
	
    @Bean   
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
    
	@Bean	
	@Conditional(MemoryClientStoreCondition.class)
	public ClientDetailsService clientDetailsService() {
		
		Map<String,ClientDetails> clientDetailsStore = new HashMap();
		
		BaseClientDetails myclient = new BaseClientDetails("myclient","","openid","authorization_code,refresh_token,client_credentials,password","CLIENT");
		myclient.setClientSecret(passwordEncoder.encode("myclientsecret"));
		clientDetailsStore.put("myclient", myclient);
		log.debug("***Added client:{}",myclient.toString());
		
		BaseClientDetails zuulclient = new BaseClientDetails("zuul","","openid","authorization_code,refresh_token","CLIENT");
		zuulclient.setClientSecret(passwordEncoder.encode("zuulsecret"));		
		Set<String> registeredRedirectUris = new HashSet<String>();		
		registeredRedirectUris.add("http://zuul:9001/authenticate");
		zuulclient.setRegisteredRedirectUri(registeredRedirectUris);
//		zuulclient.setAutoApproveScopes(Arrays.asList("openid"));
		clientDetailsStore.put("zuul", zuulclient);
		
		log.debug("***Added client:{}",zuulclient.toString());
		
		BaseClientDetails customerServiceClient = new BaseClientDetails("customer-service-client","","openid","authorization_code,refresh_token","CLIENT");
		customerServiceClient.setClientSecret(passwordEncoder.encode("customer-service-secret"));
		clientDetailsStore.put("customer-service-client", customerServiceClient);
		log.debug("***Added client:{}",customerServiceClient.toString());
		
		BaseClientDetails accountServiceClient = new BaseClientDetails("account-service-client","","openid","authorization_code,refresh_token","CLIENT");
		accountServiceClient.setClientSecret(passwordEncoder.encode("account-service-secret"));
		clientDetailsStore.put("account-service-client", accountServiceClient);
		log.debug("***Added client:{}",accountServiceClient.toString());
		
		InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService();
		clientDetailsService.setClientDetailsStore(clientDetailsStore);
		return clientDetailsService;
	}
		
	static class MemoryClientStoreCondition extends SpringBootCondition{

		@Override
		public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
	
			ConditionMessage.Builder message = ConditionMessage.forCondition("demo.clientStore Condition");
			
			String tokenStore = context.getEnvironment().getProperty("demo.clientStore");
			if(tokenStore == null || "MEMORY".equals(tokenStore)) {
				return ConditionOutcome.match(message.foundExactly("Memory clientStore"));
			}
			return ConditionOutcome.noMatch(message.didNotFind("Memory clientStore").atAll());
		}		
	}
}
